from MotorStub import MotorStub
from ThermistorDriver import ThermistorDriver
from HeaterDriver import HeaterDriver
from GCodeParser import GCodeParser
from DebugTrace import DebugTrace
from MotorController import MotorController
from HeaterController import HeaterController
from MotorDriver import MotorDriver
from ShiftRegister import OutputSR
from ADC import AnalogDigitalConverter

from threading import Thread

from time import sleep

class Controller (object):
    def __init__(self):

        self.isOpen=True
        self.currentLine=0
        self.lastRetVal=None

        self.cachedTemp= {"Bed":0, "Extruder0":0, "Extruder1":0}
        
        #Import config file
        import config
        if (config.importedConfig!=None):
            self.trace = DebugTrace("Controller",config.contTraceLvl)
            self.mc = MotorDriver(config.stepsPerMm, config.mcTraceLvl)


            if (config.heaterPollTime!=None):
                self.heatController=HeaterController(self,config.heaterPollTime)
            else:
                self.heatController=HeaterController(self)


            # Configure shift registers
            self.outputSR = OutputSR(config.outSerPin, config.outSrClkPin,config.outRClkPin,config.outNumOutputs)
            self.mc.addOutputSR (self.outputSR)
            
            self.inputSR = InputSR(config.inInputPin,config.inS1Pin,config.inClockPin,config.inNumInputs)
            self.heatController.addInputSR(self.inputSR)
            
            # Configure ADC
            self.adc = AnalogDigitalConverter(config.adcS0Pin, config.adcS1, config.adcIntPin, config.adcSamplePin)
            self.heatController.addADC(self.adc)

            ##
            #Motor Settings
            ##
            
            if (config.x==1):
                self.trace.trace(2,"Adding X Motor")
                self.x = config.xPins
                self.mc.motors["X"]=self.x


            if (config.y==1):
                self.trace.trace(2,"Adding Y Motor")
                self.y = config.yPins
                self.mc.motors["Y"]=self.y


            if (config.z==1):
                self.trace.trace(2,"Adding Z Motor")
                self.z = config.zPins
                self.mc.motors["Z"]=self.z


            if (config.e0==1):
                self.trace.trace(2,"Adding E0 Motor")
                self.e0 = config.e0Pins
                self.mc.motors["E0"]=self.e0


            if (config.e1==1):
                self.trace.trace(2,"Adding E1 Motor")
                self.e1 = config.e1Pins
                self.mc.motors["E1"]=self.e1

            self.mc.initStepPins()

            if (config.draw==1):
                self.trace.trace(2,"Enabling drawing")
                self.mc.enableDrawing(config.drawScale)


            ##
            #Heater Settings
            ##

            if (config.bedHeater!=0):
                self.trace.trace(2,"Adding Bed Heater")
                self.heatController.heaters["Bed"]=HeaterDriver(config.adcBedInput)
                self.heatControllers.heaters["Bed"].addOutputSR (self.outputSR, config.outBedHeaterPin)
                
                self.heatController.thermistors["Bed"]=ThermistorDriver(config.bedMinTemp,config.bedMaxTemp,0,self.heatController.heaters["Bed"],0)

            if (config.e0Heater!=0):
                self.trace.trace(2,"Adding E0 Heater")
                self.heatController.heaters["Extruder0"]=HeaterDriver(config.adcExtruder0Input)
                self.heatControllers.heaters["Bed"].addOutputSR (self.outputSR, config.outExtruder0Pin)
                self.heatController.thermistors["Extruder0"]=ThermistorDriver(config.e0MinTemp,config.e0MaxTemp,0,self.heatController.heaters["Extruder0"],0)

            if (config.e1Heater!=0):
                self.trace.trace(2,"Adding E1 Heater")
                self.heatController.heaters["Extruder1"]=HeaterDriver(config.adcExtruder1Input)
                self.heatControllers.heaters["Bed"].addOutputSR (self.outputSR, config.outExtruder1Pin)
                self.heatController.thermistors["Extruder1"]=ThermistorDriver(config.e0MinTemp,config.e0MaxTemp,0,self.heatController.heaters["Extruder1"],0)


            ##
            #Start heat controller
            ##
            self.heatController.trace.setDebugLevel(config.hcTraceLvl)
            Thread(target=self.heatController.heatControllerLoop).start()

            self.gcp=GCodeParser(self)
            self.gcp.trace.setDebugLevel(config.gcpTraceLvl)
            self.gcp.mh.trace.setDebugLevel(config.mhTraceLvl)
            self.gcp.mh.mc=self.mc
            

    def parseLine(self,line):
        retVal = self.gcp.parse(line)
        self.trace.trace(2,"Return code: "+retVal)
        self.lastRetVal=retVal

    def cacheTemp(self,therm,temp):
        self.cachedTemp[therm]=temp


    def write(self,line):
        self.currentLine+=1
        self.trace.trace(2,"Current line: "+str(self.currentLine))
        Thread(target=self.parseLine(line)).start()
        return

    def readline(self):
        while (self.lastRetVal==None):
            sleep(0.05)
        retVal=self.lastRetVal
        self.lastRetVal=None
        return retVal

    def close(self):
        self.heatController.running=False
        self=None
